/*
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package net.sf.l2j.gameserver.model.entity;

import java.util.Calendar;
import java.util.logging.Logger;

import javolution.util.FastSet;
import net.sf.l2j.gameserver.Announcements;
import net.sf.l2j.gameserver.instancemanager.TransformationManager;
import net.sf.l2j.gameserver.model.L2World;
import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
import net.sf.l2j.gameserver.model.olympiad.Olympiad;
import net.sf.l2j.gameserver.network.serverpackets.PlaySound;
import net.sf.l2j.gameserver.util.Broadcast;
import net.sf.l2j.util.Rnd;

/**
 * @author Laikeriz
 */
public class Biohazard
{
   enum EventState
   {
      INACTIVE,
      INACTIVATING,
      REGISTERING,
      STARTED,
      REWARDING
   }

    private final static Logger _log = Logger.getLogger(Biohazard.class.getName());
   private static EventState _state = EventState.INACTIVE;
   
   public static FastSet<L2PcInstance> _participants = new FastSet<L2PcInstance>();
   public static FastSet<L2PcInstance> _infected = new FastSet<L2PcInstance>();
   public static FastSet<L2PcInstance> _notInfected = new FastSet<L2PcInstance>();
   
   public static boolean isStarted()
   {
      if (_state == EventState.STARTED)
         return true;
      return false;
   }
   
   public static boolean isRegistering()
   {
      if (_state == EventState.REGISTERING)
         return true;
      return false;
   }
   
   public static void startRegistering()
   {
      if (_state == EventState.REGISTERING || _state == EventState.STARTED)
         return;
      Announcements.getInstance().announceToAll("Biohazard: Registro abierto.");
      Announcements.getInstance().announceToAll("Biohazard: usa \".bhreg\" para registrarte en el evento.");
      Announcements.getInstance().announceToAll("Biohazard: usa \".bhunreg\" para anular tu registro en el evento.");
      _state = EventState.REGISTERING;
      int step = 0;
      int after = 0;
      for (int i = 40; i > 0; i-=10)
      {
         switch(i)
         {
            case 40:
               step = 5;
               after = 15;
               break;
            case 30:
               step = 5;
               after = 10;
               break;
            case 20:
               step = 4;
               after = 5;
               break;
            case 10:
               step = 1;
               after = 1;
               break;
         }
         if (_state == EventState.INACTIVE)
            return;
         Announcements.getInstance().announceToAll("Biohazard: El registro se cerrara en " + after + " minuto(s).");
         try{Thread.sleep(step*60000);}catch (Exception e){}
      }
      //sound = "";
      try{Thread.sleep(60000);}catch (Exception e){}
      if (_state == EventState.INACTIVE)
         return;
      if (_participants.size() >= 2)
      {
         Announcements.getInstance().announceToAll("Biohazard: Teleportando players en 20 segundos.");
         try{Thread.sleep(20000);}catch (Exception e){}
         _state = EventState.STARTED;
         startEventAndTelePl();
      }
      else
         Announcements.getInstance().announceToAll("Biohazard: Evento cancelado por falta de participantes.");
   }
   
   public static void addParticipant(L2PcInstance player)
   {
      if (Olympiad.getInstance().isRegistered(player) || TvTEvent.isPlayerParticipant(player.getObjectId()))
      {
         player.sendMessage("Tu no puedes registrarte puesto que ya estas registrado en otro evento");
         return;
      }
      if (_state == EventState.REGISTERING && !_participants.contains(player))
      {
         _participants.add(player);
         player.sendMessage("Te has registrado en el Evento BioHazard");
      }
      else
         player.sendMessage("Ya estas registrado o el resgistro no esta abierto.");
   }
   
   public static void removeParticipant(L2PcInstance player)
   {
      if (_state == EventState.REGISTERING)
      {
         if (_participants.contains(player))
            _participants.remove(player);
         else
            player.sendMessage("Ya no estas registrado en el evento BioHazard.");
         player.setIsInBiohazard(false);
      }
      else
         player.sendMessage("No es tiempo de resgistro.");
   }
   public static void startEventAndTelePl()
   {
      if (_state == EventState.INACTIVE)
         return;
      synchronized(_participants)
      {
         for (L2PcInstance pl : _participants)
            if (pl.isOnline() == 1)
            {
               _notInfected.add(pl);
               pl._oldX = pl.getX();
               pl._oldY = pl.getY();
               pl._oldZ = pl.getZ();
               pl.teleToLocation(-17507,143206,-3911);
               pl.setTeam(0);
               pl.setIsInBiohazard(true);
               pl.untransform();
            }
      }
   Announcements.getInstance().announceToAll("Biohazard: Teleportacion terminada.");
   Announcements.getInstance().announceToAll("Biohazard: Un player sera infectado con un intratable virus transformandolo en un zombie!");
   //Announcements.getInstance().announceToAll("Biohazard: In about one minute virus will take over his body and he will become zombie!");
   try{Thread.sleep(60000);}catch (Exception e){}
   int num = Math.round(Rnd.get(_notInfected.size()-1));
   L2PcInstance infectFirst = ((L2PcInstance[])getAllNotInfected())[num];
   infectPlayer(infectFirst);
   Announcements.getInstance().announceToAll("Biohazard: El virus a infectado el cuerpo de " + infectFirst.getName() + " y ahora el quiere infectar a todo el mundo!");
   }
   
   public static void infectPlayer(L2PcInstance zombie)
   {
      if (_state == EventState.INACTIVE)
         return;
      if (zombie.isTransformed())
         zombie.untransform();
      zombie.setIsZombie(true);
      _notInfected.remove(zombie);
      _infected.add(zombie);
      TransformationManager.getInstance().transformPlayer(303, zombie);
      if (_notInfected.size() == 0)
         zombiesWin();
   }
   
   public static void onLogout(L2PcInstance playerInstance)
   {
      if (_state == EventState.REGISTERING)
         removeParticipant(playerInstance);
      else if (_state == EventState.STARTED)
      {
         playerInstance.setXYZ(playerInstance._oldX,playerInstance._oldY,playerInstance._oldZ);
         if (!playerInstance.isZombie())
            _notInfected.remove(playerInstance);
         else if (playerInstance.isZombie())
            _infected.remove(playerInstance);
         if (_notInfected.size() == 0)
            zombiesWin();
         if (_infected.size() == 0)
            playersWin();
      }
   }
   
   public static void zombiesWin()
   {
      if (_state == EventState.INACTIVE)
         return;
      Announcements.getInstance().announceToAll("Biohazard: Los Zombies han ganado.");
      Announcements.getInstance().announceToAll("Biohazard: Se recompensara y se teleportara de regreso a los participantes en 20 segundos.");
      _state = EventState.REWARDING;
      try{Thread.sleep(20000);}catch (Exception e){}
      synchronized(_infected)
      {
         for (L2PcInstance pl : _infected)
            if (pl.isOnline() == 1)
               pl.addItem("Biohazard", 6673, 1, pl, true);
      }
      synchronized(_participants)
      {
         for (L2PcInstance pl : _participants)
            if (pl.isOnline() == 1)
            {
               pl.teleToLocation(pl._oldX,pl._oldY,pl._oldZ);
               pl.setIsInBiohazard(false);
//               if (pl.inWorld() == 1)
//                  pl.setTeam(pl.getFactionId());
               if (pl.isTransformed())
                  pl.untransform();
            }
      }
      _participants.clear();
      _infected.clear();
      _notInfected.clear();
      _state = EventState.INACTIVE;
   }
   
   public static void playersWin()
   {
      Announcements.getInstance().announceToAll("Biohazard: Los players han ganado.");
      Announcements.getInstance().announceToAll("Biohazard: Se recompensara y se teleportara de regreso a los participantes en 20 segundos.");
      _state = EventState.REWARDING;
      try{Thread.sleep(20000);}catch (Exception e){}
      synchronized(_notInfected)
      {
         for (L2PcInstance pl : _notInfected)
            if (pl.isOnline() == 1)
            {
               pl.addItem("Biohazard", 6673, 1, pl, true);
            }
      }
      synchronized(_participants)
      {
         for (L2PcInstance pl : _participants)
            if (pl.isOnline() == 1)
            {
               pl.teleToLocation(pl._oldX,pl._oldY,pl._oldZ);
               pl.setIsInBiohazard(false);
//               if (pl.inWorld() == 1)
//                  pl.setTeam(pl.getFactionId());
               if (pl.isTransformed())
                  pl.untransform();
            }
      }
      _participants.clear();
      _infected.clear();
      _notInfected.clear();
      _state = EventState.INACTIVE;
   }
   
   public static L2PcInstance[] getAllNotInfected()
   {
      synchronized(_notInfected)
      {
         return _notInfected.toArray(new L2PcInstance[_notInfected.size()]);
      }
   }
   
   public static void abortEvent()
   {
      _state = EventState.INACTIVE;
      _participants.clear();
      _notInfected.clear();
      _infected.clear();
      Announcements.getInstance().announceToAll("Biohazard: Evento abortado.");
   }
}